#include <stdlib.h>
#include "SymboleValue.h"
#include "MotsCles.h"
#include <typeinfo>


////////////////////////////////////////////////////////////////////////////////
SymboleValue::SymboleValue(Symbole s, string type, unsigned int ligne) :
        Symbole(s.getChaine()) { // on herite de symbole, on le creer donc
    defini = true;
    this->ligne=ligne;
    if (s == "<ENTIER>") {
        valeur = new ValeurInt(atoi(s.getChaine().c_str()));
        this->type = ENTIER;
    }
    else if (s == "<REEL>") {
        valeur = new ValeurFloat(atof(s.getChaine().c_str()));
        this->type = REEL;
    }
    else if (s == "<CHAINE>") {
        string ch = "";
        for (unsigned int i = 1; i <= s.getChaine().size()-2; i++) // on enleve les guillement a la chaine
            ch += s.getChaine()[i];
        valeur = new ValeurString(ch); // et on la sauvegarde
        this->type = CHAINE;
    }
    else if (s == "<CARACT>") {
        valeur = new ValeurChar(s.getChaine()[1]);
        this->type = CHAR;
    }
    else {
        if (type==ENTIER) {
            valeur = new ValeurInt(1); // on initialise la valeur a 0
            this->type = ENTIER;
        }
        if (type==REEL) {
            valeur = new ValeurFloat(1.0); // 0.0
            this->type = REEL;
        }
        if (type==CHAINE) {
            valeur = new ValeurString("\0"); // "\0"
            this->type = CHAINE;
        }
        if (type==CHAR) {
            valeur = new ValeurChar('\0');// '\0'
            this->type = CHAR;
        }
        defini = false; // la valeur de la veriable n'est pas defini
    }
}


////////////////////////////////////////////////////////////////////////////////
// Attention : cette fonction (operator) n'est pas membre de la classe SymboleValue
ostream & operator <<(ostream & cout, SymboleValue symb) {
    cout << (Symbole) symb << "\t\t - " << symb.getType() << " (ligne " << symb.getLigne() <<") Valeur=";
    Valeur* val = symb.valeur;
    if (symb.defini) {
        if ( symb.getType()==ENTIER) {
            cout << ((ValeurInt*)val)->getValeur() << " ";
        }
        if ( symb.getType()==REEL) {
            cout << ((ValeurFloat*)val)->getValeur() << " ";
        }
        if ( symb.getType()==CHAINE) {
            cout << ((ValeurString*)val)->getValeur() << " ";
        }
        if ( symb.getType()==CHAR) {
            cout << ((ValeurChar*)val)->getValeur() << " ";
        }
    }
    else
        cout << "indefinie ";
    return cout;
}

Valeur*  SymboleValue::getValeur() { // accesseur
    return this->valeur;
}

void SymboleValue::setValeur(Valeur* valeur) {
    if ((type == ENTIER) && (typeid(*valeur) == typeid(ValeurFloat))) { // si on veut stoker un reel dans une varaible entier, on la cast
        ValeurInt* nv = new ValeurInt(((ValeurFloat*)valeur)->getValeur());
        this->valeur=nv;
    }
    else if ((type == REEL) && (typeid(*valeur) == typeid(ValeurInt))) { // idem, mais inv
        ValeurFloat* nv = new ValeurFloat(((ValeurInt*)valeur)->getValeur());
        this->valeur=nv;    // accesseuriq
    }
    else
        this->valeur = valeur; //sinon, rien a signaler
    defini=true;
}


void SymboleValue::Accept(NoeudVisitor& visitor) {
    if (typeid(visitor) == typeid(AfficherVisitor)) { //si on affiche, on fait un travail de presentaion
        visitor.IncresIndentation();
        visitor.VisitSymboleValue(this);
        visitor.DecresIndentation();
    }
    else { // sinon, on fait just passer
        visitor.VisitSymboleValue(this);
    }
}
